package org.third.integration.ldap.auth;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.event.EventContext;
import javax.naming.event.NamespaceChangeListener;
import javax.naming.event.NamingEvent;
import javax.naming.event.NamingExceptionEvent;
import javax.naming.event.NamingListener;
import javax.naming.event.ObjectChangeListener;
import javax.naming.ldap.UnsolicitedNotificationEvent;
import javax.naming.ldap.UnsolicitedNotificationListener;

public class LdapListener {
    public static void main(String[] args) {
        // Set up environment for creating initial context
        Hashtable<String, Object> env = new Hashtable<String, Object>(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://16.187.189.6:389");
        env.put(Context.SECURITY_PRINCIPAL, "cn=Manager,dc=maxcrc,dc=com");
        env.put(Context.SECURITY_CREDENTIALS, "1");
        try {
            // Get event context for registering listener
            String baseDN = "o=TestOrg,dc=maxcrc,dc=com";
           javax.naming.Context ctxBase= (javax.naming.Context)(new InitialContext(env).lookup(baseDN));
            javax.naming.ldap.LdapContext ldapCtx = (javax.naming.ldap.LdapContext)ctxBase;
            
            javax.naming.directory.SearchControls searchCtls = new javax.naming.directory.SearchControls();
            searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
            // String searchFilter =
            // "(&(objectClass=person)(cn=*)(uid=ktest1))";]
            String searchFilter = "cn=*";
            // String filter =
            // "(&(modifyTimestamp>=20061231080000Z)(modifyTimestamp<=20070101080000Z))";
            // //条件为 2006年12月31日8点整<=最后一次修改时间<=2007年1月1日8点整，

            String searchBase = "ou=Users";
            String returnedAtts[] = {};
            searchCtls.setReturningAttributes(returnedAtts);
            javax.naming.NamingEnumeration<SearchResult> userResult = ldapCtx.search(searchBase, searchFilter, searchCtls);
            while (userResult.hasMoreElements()) {
                SearchResult sr = (SearchResult) userResult.next();
                System.out.println("<<<::[" + sr.getName() + "]::>>>>");
            }
            
            javax.naming.event.EventDirContext evtCtx = (javax.naming.event.EventDirContext)ctxBase;
            
            // Create listener
            NamingListener unsolListener = new UnsolicitedNotificationListener() {

                public void notificationReceived(UnsolicitedNotificationEvent evt) {
                    System.out.println("received: " + evt + ",notification:" + evt.getNotification());
                }

                public void namingExceptionThrown(NamingExceptionEvent evt) {
                    System.out.println(">>> UnsolListener got an exception");
                    evt.getException().printStackTrace();
                }
            };
            NamingListener namespaceListener = new NamespaceChangeListener() {

                public void objectAdded(NamingEvent evt) {
                    System.out.println("objectAdded: " + evt.getOldBinding() + "\n=> " + evt.getNewBinding());
                    System.out.println("\tchangeInfo: " + evt.getChangeInfo());
                }

                public void objectRemoved(NamingEvent evt) {
                    System.out.println("objectRemoved: " + evt.getOldBinding() + "\n=> " + evt.getNewBinding());
                    System.out.println("\tchangeInfo: " + evt.getChangeInfo());
                }

                public void objectRenamed(NamingEvent evt) {
                    System.out.println("objectRenamed: " + evt.getOldBinding() + "\n=> " + evt.getNewBinding());
                    System.out.println("\tchangeInfo: " + evt.getChangeInfo());
                }

                public void namingExceptionThrown(NamingExceptionEvent evt) {
                    System.err.println(">>>NamespaceChangeListener Exception");
                    evt.getException().printStackTrace();
                }
            };
            NamingListener objectListener = new ObjectChangeListener() {

                public void objectChanged(NamingEvent evt) {
                    System.out.println("objectChanged: " + evt.getOldBinding() + "\n\t=> " + evt.getNewBinding());
                    System.out.println("\tchangeInfo: " + evt.getChangeInfo());
                }

                public void namingExceptionThrown(NamingExceptionEvent evt) {
                    System.err.println(">>>ObjectChangeListener Exception");
                    evt.getException().printStackTrace();
                }
            };
            // Register listener with context (all targets equivalent)
            evtCtx.addNamingListener(baseDN, EventContext.SUBTREE_SCOPE, unsolListener);
//            evtCtx.addNamingListener(baseDN, EventContext.SUBTREE_SCOPE, namespaceListener);
//            evtCtx.addNamingListener(baseDN, EventContext.SUBTREE_SCOPE, objectListener);
            System.out.println("Listener to LDAP server ...");
            // Wait 1 minutes for listener to receive events
            try {
                Thread.sleep(60000 * 60);
            } catch (InterruptedException e) {
                System.out.println("sleep interrupted");
            }
            // Not strictly necessary if we're going to close context anyhow
            evtCtx.removeNamingListener(unsolListener);
            // Close context when we're done
            ldapCtx.close();
            System.out.println("Remove Listener ...");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
}
